import platformApi from "./utils/platform";
import ErrorTypes from "./utils/errorTypes";

/**
 * 设备连接功能模块
 * @param {Object} config - 配置项对象
 * @param {string} config.connectionMode - 设备连接方式，'auto' 或 'manual'
 * @param {string} config.serviceId - 设备服务 ID
 * @param {function} config.characteristicMatch - 特征值匹配函数
 * @param {function} config.errorHandler - 异常处理函数
 * @returns {Object} - 包含手动连接和自动连接设备方法的对象
 */
export default function (config) {
  const { serviceId, characteristicMatch, errorHandler } = config;
  let deviceList = [];
  let selectedDevice = null;
  let writeChar = null;
  let notifyChar = null;
  let scanTimer = null;
  const scanTime = 10;

  /**
   * 启动设备发现
   * @returns {Promise} - 设备发现结果的 Promise
   */
  const startBluetoothDiscovery = () => {
    return new Promise(async (resolve, reject) => {
      const { available } = await getBluetoothAdapterState();

      if (!available) {
        errorHandler(
          ErrorTypes.BLUETOOTH_CONNECTION_FAILED,
          "蓝牙适配器不可用",
          new Error("蓝牙适配器不可用")
        );
        reject(new Error("蓝牙适配器不可用"));
        return;
      }

      if (scanTimer) {
        clearTimeout(scanTimer);
      }
      // 等待10s后自动结束
      scanTimer = setTimeout(async () => {
        await stopBluetoothDiscovery();
        if (config.connectionMode === "auto") {
          autoConnectDevice(false);
        }
        resolve();
      }, scanTime * 1000);

      // 开始扫描
      await new Promise((resolve, reject) => {
        platformApi.startBluetoothDevicesDiscovery({
          services: serviceId ? [serviceId] : void 0,
          allowDuplicatesKey: false,
          success: () => {
            // 注册发现监听
            platformApi.onBluetoothDeviceFound(handleDeviceFound);
            resolve();
          },
          fail: (err) => {
            console.log("扫描错误", err);
            if (err.errMsg.includes("already started")) {
              resolve();
            } else {
              errorHandler(
                ErrorTypes.DEVICE_CONNECTION_FAILED,
                `扫描设备失败: ${err.errMsg}`,
                err
              );
              reject(err);
            }
          },
        });
      });
    });
  };

  /**
   * 设备发现处理
   * @param {Object} param - 包含设备列表的对象
   * @param {Array} param.devices - 发现的设备列表
   */
  const handleDeviceFound = ({ devices }) => {
    const _devices = devices.filter((d) => checkDevice(d));

    function checkDevice(device) {
      const hasUUID =
        serviceId && device.advertisServiceUUIDs
          ? device.advertisServiceUUIDs.includes(serviceId)
          : true;
      return (
        device.connectable !== false &&
        hasUUID &&
        !deviceList.some((exist) => exist.deviceId === device.deviceId)
      );
    }

    deviceList = [...deviceList, ..._devices];

    // 用于暴露发现设备列表
    config.onDeviceFound && config.onDeviceFound(_devices, deviceList);

    if (config.connectionMode === "auto") {
      autoConnectDevice(true);
    }
  };

  /**
   * 停止设备发现
   * @returns {Promise} - 停止结果的 Promise
   */
  const stopBluetoothDiscovery = () => {
    return new Promise(async (resolve, reject) => {
      const { discovering } = await getBluetoothAdapterState();
      if (discovering) {
        platformApi.stopBluetoothDevicesDiscovery({
          success: () => {
            resolve();
          },
          fail: (err) => {
            errorHandler(
              ErrorTypes.DEVICE_CONNECTION_FAILED,
              `停止扫描设备失败: ${err.errMsg}`,
              err
            );
            reject(err);
          },
        });
      } else {
        resolve();
      }
    });
  };

  /**
   * 获取蓝牙适配器状态
   * @returns {Promise} - 蓝牙适配器状态的 Promise
   */
  const getBluetoothAdapterState = () => {
    return new Promise((resolve) => {
      platformApi.getBluetoothAdapterState({
        success: resolve,
        fail: () => resolve({ available: false, discovering: false }),
      });
    });
  };

  /**
   * 设备连接核心逻辑
   * @param {Object} device - 要连接的设备对象
   * @returns {Promise} - 设备连接结果的 Promise
   */
  const connectDevice = (device) => {
    return new Promise(async (resolve, reject) => {
      try {
        console.log("开始连接设备", device);
        // 1. 创建BLE连接
        await createBLEConnection(device.deviceId);

        // 2. 获取服务
        const services = await getBLEDeviceServices(device.deviceId);
        const primaryService = services.find((s) => s.uuid === serviceId);
        if (!primaryService) throw new Error("未找到指定服务");

        // 3. 获取特征值
        const characteristics = await getBLEDeviceCharacteristics(
          device.deviceId,
          primaryService.uuid
        );
        const { writeChar, notifyChar } = characteristicMatch(characteristics);
        if (!writeChar || !notifyChar) throw new Error("缺少必要特征值");

        selectedDevice = device;
        writeChar = writeChar;
        notifyChar = notifyChar;

        // 4. 启用通知
        await enableNotifications(
          device.deviceId,
          primaryService.uuid,
          notifyChar.uuid
        );

        setupDeviceListeners(device.deviceId);
        resolve();
      } catch (error) {
        if (error.message === "未找到指定服务") {
          errorHandler(ErrorTypes.SERVICE_NOT_FOUND, error.message, error);
        } else if (error.message === "缺少必要特征值") {
          errorHandler(
            ErrorTypes.CHARACTERISTIC_NOT_FOUND,
            error.message,
            error
          );
        } else {
          errorHandler(
            ErrorTypes.DEVICE_CONNECTION_FAILED,
            error.message,
            error
          );
        }
        reject(error);
      }
    });
  };

  /**
   * 创建BLE连接
   * @param {string} deviceId - 设备 ID
   * @returns {Promise} - 连接结果的 Promise
   */
  const createBLEConnection = (deviceId) => {
    return new Promise((resolve, reject) => {
      platformApi.createBLEConnection({
        deviceId,
        success: () => {
          resolve();
        },
        fail: (err) => {
          errorHandler(
            ErrorTypes.DEVICE_CONNECTION_FAILED,
            `连接失败: ${err.errMsg}`,
            err
          );
          reject(new Error(`连接失败: ${err.errMsg}`));
        },
      });
    });
  };

  /**
   * 获取BLE设备服务
   * @param {string} deviceId - 设备 ID
   * @returns {Promise} - 服务列表的 Promise
   */
  const getBLEDeviceServices = (deviceId) => {
    return new Promise((resolve, reject) => {
      platformApi.getBLEDeviceServices({
        deviceId,
        success: (res) => resolve(res.services),
        fail: (err) => {
          errorHandler(
            ErrorTypes.SERVICE_NOT_FOUND,
            `获取服务失败: ${err.errMsg}`,
            err
          );
          reject(new Error(`获取服务失败: ${err.errMsg}`));
        },
      });
    });
  };

  /**
   * 获取BLE设备特征值
   * @param {string} deviceId - 设备 ID
   * @param {string} serviceId - 服务 ID
   * @returns {Promise} - 特征值列表的 Promise
   */
  const getBLEDeviceCharacteristics = (deviceId, serviceId) => {
    return new Promise((resolve, reject) => {
      platformApi.getBLEDeviceCharacteristics({
        deviceId,
        serviceId,
        success: (res) => resolve(res.characteristics),
        fail: (err) => {
          errorHandler(
            ErrorTypes.CHARACTERISTIC_NOT_FOUND,
            `获取特征值失败: ${err.errMsg}`,
            err
          );
          reject(new Error(`获取特征值失败: ${err.errMsg}`));
        },
      });
    });
  };

  /**
   * 启用通知
   * @param {string} deviceId - 设备 ID
   * @param {string} serviceId - 服务 ID
   * @param {string} characteristicId - 特征值 ID
   * @returns {Promise} - 启用结果的 Promise
   */
  const enableNotifications = (deviceId, serviceId, characteristicId) => {
    return new Promise((resolve, reject) => {
      platformApi.notifyBLECharacteristicValueChange({
        deviceId,
        serviceId,
        characteristicId,
        state: true,
        success: () => {
          platformApi.onBLECharacteristicValueChange(handleDataReceived);
          resolve();
        },
        fail: (err) => {
          errorHandler(
            ErrorTypes.NOTIFICATION_ENABLE_FAILED,
            `启用通知失败: ${err.errMsg}`,
            err
          );
          reject(new Error(`启用通知失败: ${err.errMsg}`));
        },
      });
    });
  };

  /**
   * 设备事件监听设置
   * @param {string} deviceId - 设备 ID
   */
  const setupDeviceListeners = (deviceId) => {
    // 连接状态监听
    platformApi.onBLEConnectionStateChange((res) => {
      console.log("连接状态", res);
      if (!res.connected) {
        errorHandler(
          ErrorTypes.DEVICE_CONNECTION_FAILED,
          "设备已断开",
          new Error("设备已断开")
        );
      }
    });
  };

  /**
   * 手动连接设备
   */
  const connectDeviceManually = async (device) => {
    try {
      await stopBluetoothDiscovery();
      await connectDevice(device);
      console.log("设备连接成功", device);
    } catch (error) {
      console.error(error);
    }
  };

  /**
   * 自动连接设备
   * @param {boolean} isDiscovery - 是否设备发现中
   */
  const autoConnectDevice = async (isDiscovery) => {
    try {
      // 自动选择第一个设备
      if (deviceList.length > 0) {
        const device = deviceList[0];
        await stopBluetoothDiscovery();
        await connectDevice(device);
        console.log("设备连接成功", device);
      } else {
        !isDiscovery &&
          errorHandler(
            ErrorTypes.DEVICE_NOT_FOUND,
            "未找到可用设备",
            new Error("未找到可用设备")
          );
      }
    } catch (error) {
      console.error(error);
    }
  };

  /**
   * 获取设备信息
   * @returns {Object} - 设备信息对象
   */
  const getDeviceInfo = () => {
    return { selectedDevice, writeChar, notifyChar };
  };

  /**
   * 断开蓝牙设备连接
   * @returns {Promise} - 断开连接结果的 Promise
   */
  const disconnectDevice = () => {
    return new Promise((resolve, reject) => {
      if (!selectedDevice) {
        errorHandler(
          ErrorTypes.DEVICE_CONNECTION_FAILED,
          "没有已连接的设备",
          new Error("没有已连接的设备")
        );
        reject(new Error("没有已连接的设备"));
        return;
      }
      platformApi.closeBLEConnection({
        deviceId: selectedDevice.deviceId,
        success: () => {
          selectedDevice = null;
          writeChar = null;
          notifyChar = null;
          resolve();
        },
        fail: (err) => {
          errorHandler(
            ErrorTypes.DEVICE_CONNECTION_FAILED,
            `断开连接失败: ${err.errMsg}`,
            err
          );
          reject(new Error(`断开连接失败: ${err.errMsg}`));
        },
      });
    });
  };

  return {
    connectDevice: connectDeviceManually,
    startBluetoothDiscovery,
    stopBluetoothDiscovery,
    getDeviceInfo,
    disconnectDevice,
  };
}
